<?php
namespace app\common\services;

use app\common\model\AttributionInstall;
use app\common\model\AttributionTrack;
use app\common\model\AttributionEvent;
use support\Db;
use support\Log;
use support\Redis;

/**
 * 免邀请安装服务
 * 处理免邀请码安装的核心业务逻辑
 */
class InvitationFreeInstallService
{
    /**
     * 归因窗口期 (默认7天)
     */
    const ATTRIBUTION_WINDOW = 604800; // 7 days in seconds
    
    /**
     * 邀请关系有效期 (默认30天)
     */
    const INVITATION_VALIDITY = 2592000; // 30 days in seconds
    
    /**
     * 设备指纹相似度阈值
     */
    const DEVICE_SIMILARITY_THRESHOLD = 0.85;

    /**
     * 处理免邀请安装
     * 核心业务流程：设备追踪 → 归因分析 → 邀请关系建立
     */
    public function processInvitationFreeInstall($appkey, $deviceInfo, $installParams = [])
    {
        try {
            // 1. 生成设备指纹
            $deviceFingerprint = $this->generateDeviceFingerprint($deviceInfo);
            
            // 2. 查找设备追踪记录
            $trackingRecord = $this->findDeviceTracking($appkey, $deviceFingerprint);
            
            if (!$trackingRecord) {
                return [
                    'success' => false,
                    'reason' => 'No tracking record found',
                    'suggestion' => 'Please ensure the device has visited the promotion link before installation'
                ];
            }

            // 3. 执行归因分析
            $attributionResult = $this->performAttributionAnalysis($trackingRecord, $deviceInfo);
            
            if (!$attributionResult['success']) {
                return $attributionResult;
            }

            // 4. 建立邀请关系
            $invitationResult = $this->establishInvitationRelationship(
                $appkey,
                $attributionResult['tracking_id'],
                $deviceInfo,
                $attributionResult['custom_params']
            );

            // 5. 记录安装事件
            $this->recordInstallation($appkey, $deviceFingerprint, $deviceInfo, $attributionResult);

            // 6. 更新统计数据
            $this->updateInstallationStats($appkey, $attributionResult);

            return [
                'success' => true,
                'message' => 'Invitation-free installation processed successfully',
                'data' => [
                    'device_fingerprint' => $deviceFingerprint,
                    'attribution_result' => $attributionResult,
                    'invitation_result' => $invitationResult,
                    'install_id' => $this->generateInstallId($appkey, $deviceInfo['device_id'] ?? $deviceFingerprint),
                    'channel' => $attributionResult['channel'] ?? 'organic',
                    'inviter_info' => $attributionResult['inviter_info'] ?? null,
                    'custom_params' => $attributionResult['custom_params'] ?? []
                ]
            ];

        } catch (\Exception $e) {
            Log::error('Invitation-free install failed: ' . $e->getMessage());
            return [
                'success' => false,
                'reason' => 'Installation processing failed',
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * 获取安装参数（APP启动时调用）
     */
    public function getInstallParams($appkey, $deviceId, $deviceFingerprint)
    {
        // 1. 查找最近的安装记录
        $installRecord = $this->findRecentInstall($appkey, $deviceId, $deviceFingerprint);
        
        if (!$installRecord) {
            return [
                'success' => false,
                'reason' => 'No installation record found',
                'data' => [
                    'channel' => 'organic',
                    'custom_params' => [],
                    'inviter_info' => null
                ]
            ];
        }

        // 2. 获取归因信息
        $trackingRecord = AttributionTrack::where('tracking_id', $installRecord['tracking_id'])->find();
        
        if (!$trackingRecord) {
            return [
                'success' => false,
                'reason' => 'No tracking data found',
                'data' => [
                    'channel' => 'organic',
                    'custom_params' => [],
                    'inviter_info' => null
                ]
            ];
        }

        // 3. 解析自定义参数
        $customParams = json_decode($trackingRecord['custom_params'], true) ?? [];
        
        // 4. 获取邀请人信息
        $inviterInfo = $this->getInviterInfo($customParams);

        return [
            'success' => true,
            'message' => 'Install parameters retrieved successfully',
            'data' => [
                'channel' => $customParams['channel'] ?? 'organic',
                'custom_params' => $customParams,
                'inviter_info' => $inviterInfo,
                'install_time' => $installRecord['install_time'],
                'attributed_at' => $installRecord['attributed_at'],
                'match_type' => $installRecord['match_type'],
                'confidence' => $installRecord['confidence']
            ]
        ];
    }

    /**
     * 生成设备指纹
     */
    private function generateDeviceFingerprint($deviceInfo)
    {
        // 综合设备信息生成指纹
        $fingerprintData = [
            'platform' => $deviceInfo['platform'] ?? '',
            'device_model' => $deviceInfo['device_model'] ?? '',
            'os_version' => $deviceInfo['os_version'] ?? '',
            'screen_resolution' => $deviceInfo['screen_resolution'] ?? '',
            'language' => $deviceInfo['language'] ?? '',
            'timezone' => $deviceInfo['timezone'] ?? '',
            'user_agent' => $deviceInfo['user_agent'] ?? '',
            'device_id' => $deviceInfo['device_id'] ?? '',
            'android_id' => $deviceInfo['android_id'] ?? '',
            'idfa' => $deviceInfo['idfa'] ?? '',
            'idfv' => $deviceInfo['idfv'] ?? ''
        ];

        // 移除空值
        $fingerprintData = array_filter($fingerprintData);
        
        // 生成SHA256指纹
        return hash('sha256', json_encode($fingerprintData, JSON_SORT_KEYS));
    }

    /**
     * 查找设备追踪记录
     */
    private function findDeviceTracking($appkey, $deviceFingerprint)
    {
        $windowStart = date('Y-m-d H:i:s', time() - self::ATTRIBUTION_WINDOW);
        
        return AttributionTrack::where([
            'appkey' => $appkey,
            'fingerprint' => $deviceFingerprint,
            ['created_at', '>=', $windowStart]
        ])->orderBy('created_at', 'desc')->find();
    }

    /**
     * 执行归因分析
     */
    private function performAttributionAnalysis($trackingRecord, $deviceInfo)
    {
        $customParams = json_decode($trackingRecord['custom_params'], true) ?? [];
        
        // 1. 精确匹配检查
        if ($this->checkExactMatch($trackingRecord, $deviceInfo)) {
            return [
                'success' => true,
                'tracking_id' => $trackingRecord['tracking_id'],
                'match_type' => 'exact',
                'confidence' => 1.0,
                'channel' => $customParams['channel'] ?? 'organic',
                'custom_params' => $customParams,
                'reason' => 'Device fingerprint exact match'
            ];
        }

        // 2. 模糊匹配检查
        $similarityScore = $this->calculateDeviceSimilarity($trackingRecord, $deviceInfo);
        
        if ($similarityScore >= self::DEVICE_SIMILARITY_THRESHOLD) {
            return [
                'success' => true,
                'tracking_id' => $trackingRecord['tracking_id'],
                'match_type' => 'fuzzy',
                'confidence' => $similarityScore,
                'channel' => $customParams['channel'] ?? 'organic',
                'custom_params' => $customParams,
                'reason' => 'Device similarity score: ' . round($similarityScore * 100, 2) . '%'
            ];
        }

        // 3. 检查是否可以通过其他信息归因
        $fallbackResult = $this->checkFallbackAttribution($trackingRecord, $deviceInfo);
        if ($fallbackResult['success']) {
            return $fallbackResult;
        }

        return [
            'success' => false,
            'reason' => 'Unable to attribute installation with sufficient confidence',
            'similarity_score' => $similarityScore,
            'threshold' => self::DEVICE_SIMILARITY_THRESHOLD
        ];
    }

    /**
     * 检查精确匹配
     */
    private function checkExactMatch($trackingRecord, $deviceInfo)
    {
        $trackingDeviceInfo = json_decode($trackingRecord['device_info'], true) ?? [];
        
        // 检查关键设备信息是否完全匹配
        $keyFields = ['device_id', 'android_id', 'idfa', 'idfv'];
        
        foreach ($keyFields as $field) {
            if (!empty($deviceInfo[$field]) && !empty($trackingDeviceInfo[$field])) {
                if ($deviceInfo[$field] === $trackingDeviceInfo[$field]) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 计算设备相似度
     */
    private function calculateDeviceSimilarity($trackingRecord, $deviceInfo)
    {
        $trackingDeviceInfo = json_decode($trackingRecord['device_info'], true) ?? [];
        
        // 计算多维度相似度
        $similarityFactors = [];

        // 1. 平台相似度
        if (!empty($deviceInfo['platform']) && !empty($trackingDeviceInfo['platform'])) {
            $similarityFactors['platform'] = $deviceInfo['platform'] === $trackingDeviceInfo['platform'] ? 1.0 : 0.0;
        }

        // 2. 设备型号相似度
        if (!empty($deviceInfo['device_model']) && !empty($trackingDeviceInfo['device_model'])) {
            similar_text($deviceInfo['device_model'], $trackingDeviceInfo['device_model'], $modelSimilarity);
            $similarityFactors['device_model'] = $modelSimilarity / 100;
        }

        // 3. 屏幕分辨率相似度
        if (!empty($deviceInfo['screen_resolution']) && !empty($trackingDeviceInfo['screen_resolution'])) {
            $similarityFactors['screen_resolution'] = $deviceInfo['screen_resolution'] === $trackingDeviceInfo['screen_resolution'] ? 1.0 : 0.0;
        }

        // 4. 语言和时区相似度
        if (!empty($deviceInfo['language']) && !empty($trackingDeviceInfo['language'])) {
            $similarityFactors['language'] = $deviceInfo['language'] === $trackingDeviceInfo['language'] ? 1.0 : 0.0;
        }

        if (!empty($deviceInfo['timezone']) && !empty($trackingDeviceInfo['timezone'])) {
            $similarityFactors['timezone'] = $deviceInfo['timezone'] === $trackingDeviceInfo['timezone'] ? 1.0 : 0.5;
        }

        // 5. User Agent相似度
        if (!empty($deviceInfo['user_agent']) && !empty($trackingDeviceInfo['user_agent'])) {
            similar_text($deviceInfo['user_agent'], $trackingDeviceInfo['user_agent'], $uaSimilarity);
            $similarityFactors['user_agent'] = $uaSimilarity / 100;
        }

        // 计算加权平均相似度
        $weights = [
            'platform' => 0.2,
            'device_model' => 0.25,
            'screen_resolution' => 0.15,
            'language' => 0.1,
            'timezone' => 0.1,
            'user_agent' => 0.2
        ];

        $totalWeight = 0;
        $weightedSum = 0;

        foreach ($similarityFactors as $factor => $score) {
            if (isset($weights[$factor])) {
                $weightedSum += $score * $weights[$factor];
                $totalWeight += $weights[$factor];
            }
        }

        return $totalWeight > 0 ? $weightedSum / $totalWeight : 0;
    }

    /**
     * 检查备用归因方法
     */
    private function checkFallbackAttribution($trackingRecord, $deviceInfo)
    {
        // 1. IP地址一致性检查
        $currentIp = $this->getClientIp();
        if ($currentIp === $trackingRecord['ip_address']) {
            return [
                'success' => true,
                'tracking_id' => $trackingRecord['tracking_id'],
                'match_type' => 'ip_fallback',
                'confidence' => 0.6,
                'channel' => json_decode($trackingRecord['custom_params'], true)['channel'] ?? 'organic',
                'custom_params' => json_decode($trackingRecord['custom_params'], true),
                'reason' => 'IP address match fallback'
            ];
        }

        return ['success' => false, 'reason' => 'No fallback attribution available'];
    }

    /**
     * 建立邀请关系
     */
    private function establishInvitationRelationship($appkey, $trackingId, $deviceInfo, $customParams)
    {
        $inviterInfo = null;
        $relationshipEstablished = false;

        // 1. 检查是否存在邀请人信息
        if (!empty($customParams['inviter_id'])) {
            $inviterInfo = $this->getInviterDetails($customParams['inviter_id']);
            
            if ($inviterInfo) {
                // 建立邀请关系
                $this->createInvitationRecord(
                    $appkey,
                    $customParams['inviter_id'],
                    $deviceInfo['device_id'] ?? $this->generateDeviceFingerprint($deviceInfo),
                    $trackingId,
                    $customParams
                );
                
                $relationshipEstablished = true;
            }
        }

        // 2. 检查是否存在推广渠道信息
        $channelInfo = null;
        if (!empty($customParams['channel'])) {
            $channelInfo = $this->getChannelDetails($customParams['channel']);
        }

        return [
            'relationship_established' => $relationshipEstablished,
            'inviter_info' => $inviterInfo,
            'channel_info' => $channelInfo,
            'invitation_params' => [
                'inviter_id' => $customParams['inviter_id'] ?? null,
                'channel' => $customParams['channel'] ?? null,
                'scene' => $customParams['scene'] ?? null
            ]
        ];
    }

    /**
     * 记录安装事件
     */
    private function recordInstallation($appkey, $deviceFingerprint, $deviceInfo, $attributionResult)
    {
        $installData = [
            'install_id' => $this->generateInstallId($appkey, $deviceInfo['device_id'] ?? $deviceFingerprint),
            'appkey' => $appkey,
            'device_id' => $deviceInfo['device_id'] ?? $deviceFingerprint,
            'fingerprint' => $deviceFingerprint,
            'tracking_id' => $attributionResult['tracking_id'],
            'channel' => $attributionResult['channel'] ?? 'organic',
            'match_type' => $attributionResult['match_type'],
            'confidence' => $attributionResult['confidence'],
            'install_time' => date('Y-m-d H:i:s'),
            'attributed_at' => date('Y-m-d H:i:s'),
            'custom_params' => json_encode($attributionResult['custom_params'] ?? []),
            'device_info' => json_encode($deviceInfo),
            'inviter_id' => $attributionResult['custom_params']['inviter_id'] ?? null,
            'status' => 'completed'
        ];

        AttributionInstall::create($installData);

        // 记录安装事件
        $this->trackEvent($appkey, $deviceFingerprint, 'install', [
            'channel' => $attributionResult['channel'] ?? 'organic',
            'match_type' => $attributionResult['match_type'],
            'confidence' => $attributionResult['confidence']
        ]);
    }

    /**
     * 更新安装统计
     */
    private function updateInstallationStats($appkey, $attributionResult)
    {
        $channel = $attributionResult['channel'] ?? 'organic';
        $date = date('Y-m-d');

        // 更新渠道统计
        $this->updateChannelStats($appkey, $channel, 'install');

        // 更新应用统计
        $this->updateAppStats($appkey, 'install');

        // 更新邀请统计（如果有邀请人）
        if (!empty($attributionResult['custom_params']['inviter_id'])) {
            $this->updateInvitationStats(
                $attributionResult['custom_params']['inviter_id'],
                $appkey,
                'successful_invitation'
            );
        }
    }

    /**
     * 查找最近的安装记录
     */
    private function findRecentInstall($appkey, $deviceId, $deviceFingerprint)
    {
        $installModel = new AttributionInstall();
        
        return $installModel->where(function($query) use ($deviceId, $deviceFingerprint) {
            $query->where('device_id', $deviceId)
                  ->whereOr('fingerprint', $deviceFingerprint);
        })->where('appkey', $appkey)
          ->orderBy('install_time', 'desc')
          ->find();
    }

    /**
     * 获取邀请人信息
     */
    private function getInviterInfo($customParams)
    {
        if (empty($customParams['inviter_id'])) {
            return null;
        }

        // 这里应该查询用户表获取邀请人信息
        // 暂时返回模拟数据
        return [
            'user_id' => $customParams['inviter_id'],
            'nickname' => 'User_' . substr($customParams['inviter_id'], -6),
            'avatar' => 'https://example.com/avatar/default.png'
        ];
    }

    /**
     * 获取邀请人详情
     */
    private function getInviterDetails($inviterId)
    {
        // 这里应该查询数据库获取真实的邀请人信息
        // 暂时返回模拟数据
        return [
            'user_id' => $inviterId,
            'nickname' => 'Inviter_' . substr($inviterId, -6),
            'avatar' => 'https://example.com/avatar/inviter.png'
        ];
    }

    /**
     * 获取渠道详情
     */
    private function getChannelDetails($channel)
    {
        // 这里应该查询渠道表获取渠道信息
        // 暂时返回模拟数据
        return [
            'channel_code' => $channel,
            'channel_name' => ucfirst($channel) . ' Channel',
            'channel_type' => 'promotion'
        ];
    }

    /**
     * 创建邀请记录
     */
    private function createInvitationRecord($appkey, $inviterId, $inviteeId, $trackingId, $customParams)
    {
        $invitationData = [
            'appkey' => $appkey,
            'inviter_id' => $inviterId,
            'invitee_id' => $inviteeId,
            'tracking_id' => $trackingId,
            'channel' => $customParams['channel'] ?? 'direct',
            'scene' => $customParams['scene'] ?? 'unknown',
            'status' => 'completed',
            'created_at' => date('Y-m-d H:i:s'),
            'expired_at' => date('Y-m-d H:i:s', time() + self::INVITATION_VALIDITY)
        ];

        // 这里应该插入邀请记录表
        // Db::table('gf_invitations')->insert($invitationData);
        
        return true;
    }

    /**
     * 记录事件
     */
    private function trackEvent($appkey, $fingerprint, $eventType, $eventData)
    {
        $eventId = $this->generateEventId($appkey, $fingerprint, $eventType);
        
        $eventData = [
            'event_id' => $eventId,
            'appkey' => $appkey,
            'fingerprint' => $fingerprint,
            'event_type' => $eventType,
            'event_data' => json_encode($eventData),
            'created_at' => date('Y-m-d H:i:s')
        ];

        AttributionEvent::create($eventData);
    }

    /**
     * 更新渠道统计
     */
    private function updateChannelStats($appkey, $channel, $metric)
    {
        $date = date('Y-m-d');
        $cacheKey = "channel_stats:{$appkey}:{$channel}:{$date}";
        
        Redis::hincrby($cacheKey, $metric, 1);
        Redis::expire($cacheKey, 86400 * 30); // 保留30天
    }

    /**
     * 更新应用统计
     */
    private function updateAppStats($appkey, $metric)
    {
        $date = date('Y-m-d');
        $cacheKey = "app_stats:{$appkey}:{$date}";
        
        Redis::hincrby($cacheKey, $metric, 1);
        Redis::expire($cacheKey, 86400 * 30); // 保留30天
    }

    /**
     * 更新邀请统计
     */
    private function updateInvitationStats($inviterId, $appkey, $metric)
    {
        $date = date('Y-m-d');
        $cacheKey = "invitation_stats:{$inviterId}:{$appkey}:{$date}";
        
        Redis::hincrby($cacheKey, $metric, 1);
        Redis::expire($cacheKey, 86400 * 30); // 保留30天
    }

    /**
     * 生成安装ID
     */
    private function generateInstallId($appkey, $deviceId)
    {
        return md5($appkey . $deviceId . microtime(true));
    }

    /**
     * 生成事件ID
     */
    private function generateEventId($appkey, $fingerprint, $eventType)
    {
        return md5($appkey . $fingerprint . $eventType . microtime(true));
    }

    /**
     * 获取客户端IP
     */
    private function getClientIp()
    {
        $ipKeys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'];
        foreach ($ipKeys as $key) {
            if (!empty($_SERVER[$key])) {
                $ips = explode(',', $_SERVER[$key]);
                return trim($ips[0]);
            }
        }
        return '0.0.0.0';
    }
}